package org.mtree.context;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * 上下文处理工具
 * 
 * @author rushman
 */
public class ContextFactoryManager {

    private static final HashMap<Class<?>, ContextFactory> factories = new HashMap<>();

    public static void registerFactory(Class<?> clazz, ContextFactory factory) {
        synchronized (factories) {
            factories.put(clazz, factory);
        }
    }

    public static ContextFactory find(Class<?> clazz) {
        Set<Class<?>> classSet = new HashSet<>();
        classSet.add(clazz);
        return find(classSet, new HashSet<>());
    }

    private static ContextFactory find(Set<Class<?>> classes, Set<Class<?>> scanned) {
        synchronized (factories) {
            ContextFactory factory = null;
            Set<Class<?>> superClasses = new HashSet<>();
            Iterator<Class<?>> iter = classes.iterator();
            while (factory == null && iter.hasNext()) {
                Class<?> clazz = iter.next();
                if (scanned.contains(clazz)) {
                    continue;
                }

                factory = factories.get(clazz);

                if (factory != null) {
                    return factory;
                }

                scanned.add(clazz);
                superClasses.add(clazz.getSuperclass());
                superClasses.addAll(Arrays.asList(clazz.getInterfaces()));
            }

            return find(superClasses, scanned);
        }
    }

}
